package ui.core 
{
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.errors.IllegalOperationError;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.utils.Dictionary;
	import ui.events.SEvent;
	import utils.MyUtils;

	
	use namespace ui_namespace;
	/**
	 * Main component 
	 * for all controls
	 * 
	 * ...
	 * @author SChabanov
	 */
	public class BaseComponent implements IBaseComponent
	{
				
		private var _listeners:Dictionary = new Dictionary(true)
		private var _order:int = -1;
		
		protected var _name:String;
		protected var _size:Size = new Size(100,100)
		protected var _position:Point = new Point(0,0);
						
		[Event( name="created",type="ui.events.SEvent")]
		[Event( name="destroyed",type="ui.events.SEvent")]
		
		protected var _container:Sprite = new Sprite();
		
		public function BaseComponent(self:BaseComponent) 
		{
			if (self != this)
			{
				throw new IllegalOperationError("this is like Abstract class must by base for others");
			}
			_name = MyUtils.createUID(this);
			_container.addEventListener(Event.ADDED_TO_STAGE, onAddedHandler,false, 0, true);
		}
		
		private function onAddedHandler(e:Event):void 
		{
			_container.removeEventListener(Event.ADDED_TO_STAGE, onAddedHandler);
			_container.addEventListener(Event.REMOVED_FROM_STAGE, onRemovedHandler, false, 0, true);
			onCreated();
			if (_container.hasEventListener(SEvent.S_CREATED))_container.dispatchEvent(new SEvent(SEvent.S_CREATED));
			invalidate();
		}		
		
			
		private function onRemovedHandler(e:Event):void 
		{
			//_container.removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedHandler);
			if(_container.hasEventListener(SEvent.S_DESTROYED))_container.dispatchEvent(new SEvent(SEvent.S_DESTROYED));
			for (var type:String in _listeners) 
			{
				_container.removeEventListener(type, _listeners[type]);
			}
			dispose();
			
		}
			
		/**
		 * 
		 */		
		
		public function set visible(value:Boolean):void
		{
			_container.visible = value;
		}
		
		public function get visible():Boolean
		{
			return _container.visible;
		}
		 
		public function enabled(value:Boolean):void
		{
			//override
		}
		
		public function move(x:Number,y:Number):void
		{
			_position.x = x;
			_position.y = y;
			_container.x = x;
			_container.y = y;
		}
		
		public function set y(value:Number):void
		{
			_container.y = value;
			_position.y = value;
		}
		
		public function set x(value:Number):void
		{
			_container.x = value;
			_position.x = value;
		}
							
		public function setSize(w:Number,h:Number):void
		{
			_size.width = w;
			_size.height = h;
			invalidate();
		}
		/**
		 * 
		 * @param	d
		 */
		public function create(d:DisplayObjectContainer,index:int = -1):void
		{
			if (_container.parent != null) throw new Error("component created already");
			if (d)
			{
				if (index < 0)
				{
					d.addChild(_container);
					_order = d.getChildIndex(_container);
				}else {
					index = Math.min(d.numChildren, index);
					d.addChildAt(_container, index);
					_order = index;
				}
				//_container.dispatchEvent(new SEvent(SEvent.S_CREATED));
			
			}else {
				throw Error("parent is null")
			}
		}
		/**
		 * 
		 */
		public function destroy():void
		{
			if (_container.parent)
			{
				_container.parent.removeChild(_container);
			}
		}
		
		/**
		 * change child index
		 * @param	order can be greater than numChildren
		 */
		public function changeOrder(order:int):void
		{
			
			if (_container.parent)
			{
				this._order = order;
				_order = Math.max(_order, 0);
				_order = Math.min(_order, _container.parent.numChildren);
				_container.parent.setChildIndex(_container, _order);
			}
		}
		
		public function get order():int
		{
			return _order;
		}
		
		/**
		 * 
		 */
		public function get size():Size
		{
			return _size;
		}
		
		/**
		 * 
		 */
		public function get position():Point
		{
			return _position;
		}
				 
		public function invalidate():void
		{			
			_container.graphics.clear();
			_container.graphics.lineStyle(1, 0xFF0000);
			_container.graphics.beginFill(0, .5);
			_container.graphics.drawRect(0, 0, _size.width, _size.height);
			_container.graphics.endFill();
		}
			
		
		/**
		 * must be overriden
		 * call when REMOVED_FROM_STAGE event 
		 */
		protected function dispose():void
		{
			
		}
		
		
		protected function onCreated():void 
		{
			
		}
		/**
		 * 
		 */		
		/**
		 * addEventLisenter 
		 * Event must be SEvent
		 * s
		 * @param	type
		 * @param	listener
		 * @param	priority
		 */
		public function addListener(type:String,listener:Function,priority:int = 0):void
		{
			if (type.charAt(0) == "s")
			{
				if (_listeners[type] != null) return;
				_listeners[type] = listener;
				_container.addEventListener(type, listener, false, priority, true);
			}else {
				throw new Error("type must be SEvent or inheritor")
			}
			
		}
		
		public function removeListener(type:String,listener:Function):void
		{
			_container.removeEventListener(type, listener);
		}
		
		/* INTERFACE ui.core.IBaseComponent */
		
		public function get name():String 
		{
			return _name;
		}
		 
	}

}